
from datetime import datetime
import json


from django.shortcuts import render
from django.http import HttpResponse,JsonResponse
from django.views.generic import View
from rest_framework.generics import CreateAPIView, ListAPIView
from rest_framework.response import Response
from rest_framework.views import APIView

from .models import BookInfo,HeroInfo,User,UserToken
from rest_framework.viewsets import ModelViewSet
from rest_framework import mixins
from rest_framework.viewsets import GenericViewSet
from rest_framework.decorators import action
from rest_framework import exceptions
from rest_framework.authentication import SessionAuthentication,BasicAuthentication
from rest_framework.permissions import IsAuthenticated
from rest_framework.throttling import UserRateThrottle
from django_filters.rest_framework import DjangoFilterBackend
from rest_framework.filters import OrderingFilter
from rest_framework.pagination import PageNumberPagination

# Create your views here.
# http://127.0.0.1:8000/sixstart/weather/changsha/2020/
from .serializers import BookInfoSerializer,HeroInfoSerializer,UserSerializer


def weather(request,city,year):
    # 天气视图函数
    print(city)
    print(year)
    return HttpResponse("%s 在%s年的天气。" % (city,year))
    #return HttpResponse("天气真好")

# http://127.0.0.1:8000/sixstart/q/?a=12&b=654&c=987
def chaxun(request):
    # 查询参数
    print(request.META['CONTENT_TYPE'])
    print(request.GET.get('a')) # get去?问号后面的参数
    print(request.GET.get('b'))  # get去?问号后面的参数
    print(request.GET.get('c'))  # get去?问号后面的参数
    print(request.GET.getlist('a'))
    return HttpResponse("OK")


def get_body(request):
    # post请求体
    # body请求
    # from 表单请求
    a = request.POST.get("a")
    b = request.POST.get("b")
    alist = request.POST.get('a')
    print(a)
    print(b)
    print(alist)
    return HttpResponse("OK")

# 非表单数据
# 接受json格式
def get_body_json(request):
    # get 方法没有请求体，可以是post put
    # postman 请求 row  参数为json格式
    json_str = request.body
    req_dict = json.loads(json_str)
    print(req_dict['a'])
    print(req_dict['b'])
    return HttpResponse("OK")

# HttpResponse
'''
视图在接收请求并处理后，必须返回HttpResponse对象或子对象。
HttpRequest对象由Django创建，HttpResponse对象由开发人员创建。
'''
def index(request):
    return HttpResponse(content="响应体",content_type='text/html;charset=utf-8',status=200)

#可以通过HttpResponse对象中的set_cookie方法来设置cookie。
# HttpResponse.set_cookie(cookie名, value=cookie值, max_age=cookie有效期)
def demo_cookie(request):
    response = HttpResponse("ok")
    response.set_cookie('sixstar1','python1') # 临时cookie
    response.set_cookie('sixstar2','python2',max_age=3600) # 有效期一小时
    return response

def get_cookie(request):
    cookie1 = request.COOKIES.get('sixstar1')
    return HttpResponse(content=cookie1)


# 类视图
class DemoClass(View):
    # get 请求
    def get(self,request):
        return render(request,'regist.html')
    # 处理 post请求
    def post(self,request):
        return HttpResponse("这里实现逻辑处理")


class BooksApiView(View):
    #  对图书的查询和增加
    def get(self,request):
        # 查询所有图书
        queryset = BookInfo.objects.all()
        book_list=[]
        for book in queryset:
            book_list.append({
                'id':book.id,
                'btitle':book.btitle,
                'bpub_date':book.bpub_date,
            })
        return JsonResponse({'data':book_list})

    def post(self,request):
        # 新增图书
        json_str = request.body
        book_dict = json.loads(json_str)
        print(book_dict)

        book = BookInfo.objects.create(
            btitle=book_dict.get('btitle'),
            bpub_date = datetime.strptime(book_dict.get('bpub_date'), '%Y-%m-%d').date()
        )
        return JsonResponse({
            'id': book.id,
            'btitle': book.btitle,
            'bpub_date': book.bpub_date,
            'bread': book.bread,
            'bcomment': book.bcomment,
        },status=201)


class BookAPIView(View):
    # 查询单个数据
    def get(self,request,pk):
        # 获取单个图书信息
        try:
            book = BookInfo.objects.get(pk=pk)
        except BookInfo.DoesNotExist:
            return JsonResponse({
                'reCode':-1,
                "msg":"查询失败"

        })

        return JsonResponse({
            'id': book.id,
            'btitle': book.btitle,
            'bpub_date': book.bpub_date,
            'bread': book.bread,
            'bcomment': book.bcomment,
        })

    # 修改数据
    def put(self,request,pk):
        try:
            book = BookInfo.objects.get(pk=pk)
        except BookInfo.DoesNotExist:
            return HttpResponse(status=404)
        json_str = request.body
        book_dict = json.loads(json_str)
        book.btitle = book_dict.get('btitle')
        book.bpub_date = datetime.strptime(book_dict.get('bpub_date'), '%Y-%m-%d').date()
        book.save()
        return JsonResponse({
            'id': book.id,
            'btitle': book.btitle,
            'bpub_date': book.bpub_date,
            'bread': book.bread,
            'bcomment': book.bcomment,

        })

    # 删除
    def delete(self,request,pk):
        try:
            book = BookInfo.objects.get(pk=pk)
        except BookInfo.DoesNotExist:
            return HttpResponse(status=404)
        book.delete()
        return JsonResponse({"recode":0,"msg":"删除成功"})



# rest_framework 练习

class BookInfoViewSet(ModelViewSet):
    # 图书的数据
    queryset = BookInfo.objects.all()
    serializer_class = BookInfoSerializer

    # 127.0.0.1:8000/books/  get 可以访问获取所有数据的接口
    '''
    post  127.0.0.1:8000/books/   
    '''


def shell(request):
    #序列化使用
    # 先查询出一个图书对象
    #book = BookInfo.objects.get(id=2)
    book_qs = BookInfo.objects.all()
    # 构造序列化器对象
    serializer = BookInfoSerializer(book_qs,many=True)
    print(serializer.data)
    return JsonResponse({'data': serializer.data})


#关联对象嵌套序列化
def shellTwo(request):
    hero = HeroInfo.objects.get(id=6)
    serializer = HeroInfoSerializer(hero)
    return JsonResponse({'data':serializer.data})


# 反序列化
def demo_shell(request):
    #data = {'bpub_date':20200520}
    data = {'btitle':"python"}
    serializer = BookInfoSerializer(data=data)
    if serializer.is_valid():
        print("正确")
    else:
        print("错误")
    print(serializer.errors)
    # {'btitle': [ErrorDetail(string='该字段是必填项。', code='required')], 'bpub_date': [ErrorDetail(string='日期格式错误。请从这些格式中选择：YYYY-MM-DD。', code='invalid')]}
    return HttpResponse("OK")


# 对<field_name>字段进行验证，如
def validateField(request):
        data = {"btitle":'python'}
        serializer = BookInfoSerializer(data=data)
        serializer.is_valid()
        print(serializer.is_valid())
        print(serializer.errors)
        if serializer.is_valid():
            return JsonResponse({"msg":"成功"})
        else:
            return JsonResponse({'data': serializer.errors})


def validate(request):
    data = {'btitle':'about django','bread':10,'bcomment':20}
    s = BookInfoSerializer(data=data)
    if s.is_valid():
        return JsonResponse({"msg":"成功"})
    else:
        return JsonResponse({'data': s.errors})


# 注册小案例
class RegView(CreateAPIView):
    queryset = User.objects.all()
    serializer_class = UserSerializer



# 两大基类
class ApiTestView(APIView):
    # # 身份认证类
    # authentication_classes =
    # #权限检查类
    # permission_classes =
    # # 流量控制类，流量的意思就是一个访问的频次
    # throttle_classes =

    def get(self,request):
        # 处理逻辑
        pass
    pass


# 视图集ViewSet
'''
list() 提供一组数据
retrieve() 提供单个数据
create() 创建数据
update() 保存数据
destory() 删除数据
ViewSet视图集类不再实现get()、post()等方法，而是实现动作 action 如 list() 、create() 等。

视图集只在使用as_view()方法的时候，才会将action动作与具体请求方式对应上。
http://127.0.0.1:8000/sixstart/books/   获取所有数据
http://127.0.0.1:8000/sixstart/books/latest/  获取最后一条数据
http://127.0.0.1:8000/sixstart/books/1/   获取单独一条数据
http://127.0.0.1:8000/sixstart/books/1/read/ 修改数据 put


'''

class BookInfoViewSet(mixins.ListModelMixin,mixins.RetrieveModelMixin,GenericViewSet):
    queryset = BookInfo.objects.all()
    serializer_class = BookInfoSerializer

    # detail 为False 表示不需要处理具体的BookInfo对象
    @action(methods=['get'],detail=False)
    def latest(self,request):
        # 返回最新的图书信息
        # 获取最后一条数据
        book = BookInfo.objects.latest('id')
        serializer = self.get_serializer(book)
        return Response(serializer.data)

    @action(methods=['put'],detail=True)
    def read(self,request,pk):
        # 修改图书的阅读量数据
        book = self.get_object()
        book.bread = request.data.get('read')
        book.save()
        serializer = self.get_serializer(book)
        return Response(serializer.data)


#认证Authentication
class AuthenView(object):
    # 自定义认证
    def authenticate(self,request):
        token = request._request.GET.GET("token")
        token_obj =UserToken.objects.filter(token=token).first()

        if not token_obj:
            raise exceptions.AuthenticationFailed("用户认证失败")
        return (token_obj.user,token_obj)


# 可选分页器
'''
page_size 每页数目
page_query_param 前端发送的页数关键字名，默认为"page"
page_size_query_param 前端发送的每页数目关键字名，默认为None
max_page_size 前端最多能设置的每页数量
'''

class StandardPageNumberPagination(PageNumberPagination):
    page_size_query_param = 'page_size'
    max_page_size = 10


class BookInfoAuthen(ModelViewSet):
    # 查询视图
   # authentication_classes = [AuthenView]
    #authentication_classes = [SessionAuthentication,BasicAuthentication]
    # 单独设置权限  IsAuthenticated 代表必须登录认证后才允许访问，单独对视图权限设置
    #permission_classes = (IsAuthenticated)
    # 限流
    #throttle_classes = [UserRateThrottle]
    # "detail": "请求超过了限速。 Expected available in 86359 seconds."
    # queryset = BookInfo.objects.all()
    # serializer_class = BookInfoSerializer
    # # 过滤 http://127.0.0.1:8000/sixstart/authen/?btitle=西游记
    # filterset_fields = ('btitle', 'bread',)
    # #排序  http://127.0.0.1:8000/sixstart/authen/?ordering=bread
    # filter_backends = [OrderingFilter]
    # ordering_fields = ("id",'bread','bpub_date')
    # 分页 # http://127.0.0.1:8000/sixstart/authen/?page=2&page_size=2
    #print(request.data)
    queryset = BookInfo.objects.all().order_by('id')
    serializer_class = BookInfoSerializer
    pagination_class = StandardPageNumberPagination




























